# -*- coding: utf-8 -*-

from odoo import models, fields, api, _
from odoo.exceptions import UserError, ValidationError


class CpqQuotation(models.Model):
    _name = 'cpq.quotation'
    _description = 'CPQ报价单'
    _inherit = ['mail.thread', 'mail.activity.mixin']
    _rec_name = 'number'
    _order = 'create_date desc, id desc'
    
    # ============ 基本信息 ============
    number = fields.Char(
        string='报价单号',
        required=True,
        copy=False,
        readonly=True,
        default=lambda self: _('New'),
        tracking=True
    )
    
    name = fields.Char(
        string='项目名称',
        required=True,
        tracking=True
    )
    
    version = fields.Integer(
        string='版本号',
        default=1,
        tracking=True,
        help='报价版本号，变更后递增'
    )
    
    active = fields.Boolean(
        string='有效',
        default=True
    )
    
    company_id = fields.Many2one(
        'res.company',
        string='公司',
        required=True,
        default=lambda self: self.env.company
    )
    
    currency_id = fields.Many2one(
        'res.currency',
        string='货币',
        required=True,
        default=lambda self: self.env.company.currency_id
    )
    
    # ============ 客户信息 ============
    partner_id = fields.Many2one(
        'res.partner',
        string='客户',
        required=True,
        tracking=True
    )
    
    customer_code = fields.Char(
        string='客户项目代码',
        help='客户提供的项目编号'
    )
    
    end_customer = fields.Char(
        string='最终客户(OEM)',
        help='例如: 奔驰、宝马',
        tracking=True
    )
    
    vehicle_model = fields.Char(
        string='车型',
        help='例如: E级W214',
        tracking=True
    )
    
    # ============ 业务信息 ============
    rfq_date = fields.Date(
        string='RFQ日期',
        default=fields.Date.context_today,
        required=True
    )
    
    valid_until = fields.Date(
        string='报价有效期',
        compute='_compute_valid_until',
        store=True,
        readonly=False
    )
    
    salesperson_id = fields.Many2one(
        'res.users',
        string='销售负责人',
        default=lambda self: self.env.user,
        tracking=True
    )
    
    # ============ 产品配置 ============
    product_tmpl_id = fields.Many2one(
        'product.template',
        string='产品模板',
        required=True,
        domain=[('is_configurable', '=', True)]
    )
    
    configuration_id = fields.Many2one(
        'cpq.configuration',
        string='产品配置',
        copy=True
    )
    
    # ============ 数量与周期 ============
    quantity = fields.Float(
        string='预计总产量',
        required=True,
        default=100000.0,
        tracking=True
    )
    
    annual_quantity = fields.Float(
        string='年度产量'
    )
    
    lifecycle_years = fields.Float(
        string='项目生命周期(年)',
        default=5.0
    )
    
    sop_date = fields.Date(
        string='SOP日期',
        help='Start of Production - 量产开始日期'
    )
    
    # ============ 成本与价格 ============
    cost_model_id = fields.Many2one(
        'cpq.cost.model',
        string='成本模型',
        copy=True
    )
    
    unit_cost = fields.Monetary(
        string='单件成本',
        related='cost_model_id.total_cost',
        store=True,
        currency_field='currency_id'
    )
    
    unit_price = fields.Monetary(
        string='单件报价',
        required=True,
        tracking=True,
        currency_field='currency_id'
    )
    
    total_amount = fields.Monetary(
        string='总金额',
        compute='_compute_total',
        store=True,
        currency_field='currency_id'
    )
    
    margin_amount = fields.Monetary(
        string='利润金额',
        compute='_compute_margin',
        store=True,
        currency_field='currency_id'
    )
    
    margin_rate = fields.Float(
        string='利润率(%)',
        compute='_compute_margin',
        store=True,
        digits=(16, 2)
    )
    
    # ============ 状态流转 ============
    state = fields.Selection([
        ('draft', '草稿'),
        ('configured', '已配置'),
        ('costed', '已核算'),
        ('priced', '已定价'),
        ('submitted', '已提交审批'),
        ('approved', '已批准'),
        ('sent', '已发送客户'),
        ('won', '赢单'),
        ('lost', '丢单'),
        ('cancelled', '已取消')
    ], string='状态', default='draft', tracking=True, required=True)
    
    # ============ 审批 ============
    approval_ids = fields.One2many(
        'cpq.approval',
        'quotation_id',
        string='审批记录'
    )
    
    approval_status = fields.Selection([
        ('none', '无需审批'),
        ('pending', '待审批'),
        ('approved', '审批通过'),
        ('rejected', '审批拒绝')
    ], string='审批状态', compute='_compute_approval_status', store=True)
    
    # ============ 变更管理 ============
    parent_quotation_id = fields.Many2one(
        'cpq.quotation',
        string='原报价单',
        help='如果是变更版本，关联原始报价',
        copy=False
    )
    
    child_quotation_ids = fields.One2many(
        'cpq.quotation',
        'parent_quotation_id',
        string='变更版本'
    )
    
    change_description = fields.Text(
        string='变更说明'
    )
    
    change_request_id = fields.Many2one(
        'cpq.change.request',
        string='变更请求',
        copy=False
    )
    
    # ============ 备注 ============
    notes = fields.Text(
        string='内部备注'
    )
    
    customer_notes = fields.Text(
        string='客户备注',
        help='显示在报价单上的备注信息'
    )
    
    # ============ 统计字段 ============
    approval_count = fields.Integer(
        string='审批数量',
        compute='_compute_approval_count'
    )
    
    # ============ 计算字段 ============
    @api.depends('rfq_date')
    def _compute_valid_until(self):
        """默认报价有效期为30天"""
        for record in self:
            if record.rfq_date:
                record.valid_until = fields.Date.add(record.rfq_date, days=30)
            else:
                record.valid_until = False
    
    @api.depends('unit_price', 'quantity')
    def _compute_total(self):
        """计算总金额"""
        for record in self:
            record.total_amount = record.unit_price * record.quantity
    
    @api.depends('unit_price', 'unit_cost')
    def _compute_margin(self):
        """计算利润金额和利润率"""
        for record in self:
            record.margin_amount = (record.unit_price - record.unit_cost) * record.quantity
            if record.unit_price > 0:
                record.margin_rate = ((record.unit_price - record.unit_cost) / record.unit_price) * 100
            else:
                record.margin_rate = 0.0
    
    @api.depends('approval_ids.state')
    def _compute_approval_status(self):
        """计算审批状态"""
        for record in self:
            if not record.approval_ids:
                record.approval_status = 'none'
            elif any(approval.state == 'rejected' for approval in record.approval_ids):
                record.approval_status = 'rejected'
            elif all(approval.state == 'approved' for approval in record.approval_ids):
                record.approval_status = 'approved'
            else:
                record.approval_status = 'pending'
    
    @api.depends('approval_ids')
    def _compute_approval_count(self):
        """计算审批数量"""
        for record in self:
            record.approval_count = len(record.approval_ids)
    
    # ============ CRUD方法 ============
    @api.model
    def create(self, vals):
        """创建报价单时自动生成编号"""
        if vals.get('number', _('New')) == _('New'):
            vals['number'] = self.env['ir.sequence'].next_by_code('cpq.quotation') or _('New')
        return super(CpqQuotation, self).create(vals)
    
    def copy(self, default=None):
        """复制报价单时增加版本号"""
        default = dict(default or {})
        if self.parent_quotation_id:
            default['version'] = self.version + 1
        else:
            default['version'] = 1
        default['state'] = 'draft'
        return super(CpqQuotation, self).copy(default)
    
    # ============ 约束 ============
    @api.constrains('unit_price', 'unit_cost')
    def _check_price_cost(self):
        """检查价格不能低于成本(可警告但不阻止)"""
        for record in self:
            if record.unit_cost > 0 and record.unit_price < record.unit_cost:
                # 只是记录活动，不阻止
                record.activity_schedule(
                    'mail.mail_activity_data_warning',
                    summary='报价低于成本',
                    note=f'警告: 报价{record.unit_price}低于成本{record.unit_cost}，利润率为负！',
                    user_id=record.salesperson_id.id
                )
    
    @api.constrains('quantity')
    def _check_quantity(self):
        """检查数量必须大于0"""
        for record in self:
            if record.quantity <= 0:
                raise ValidationError('预计总产量必须大于0！')
    
    # ============ 业务方法 ============
    def action_configure_product(self):
        """打开产品配置向导"""
        self.ensure_one()
        return {
            'type': 'ir.actions.act_window',
            'name': '产品配置',
            'res_model': 'cpq.configuration.wizard',
            'view_mode': 'form',
            'target': 'new',
            'context': {
                'default_quotation_id': self.id,
                'default_product_tmpl_id': self.product_tmpl_id.id
            }
        }
    
    def action_calculate_cost(self):
        """触发成本核算"""
        self.ensure_one()
        
        if not self.configuration_id:
            raise UserError('请先完成产品配置！')
        
        # 创建或更新成本模型
        if not self.cost_model_id:
            cost_model = self.env['cpq.cost.model'].create({
                'quotation_id': self.id,
                'product_id': self.product_tmpl_id.product_variant_id.id,
                'estimated_quantity': self.quantity,
                'annual_quantity': self.annual_quantity,
                'lifecycle_years': self.lifecycle_years
            })
            self.cost_model_id = cost_model
        else:
            self.cost_model_id.write({
                'estimated_quantity': self.quantity,
                'annual_quantity': self.annual_quantity,
                'lifecycle_years': self.lifecycle_years
            })
        
        # 自动生成成本明细
        self.cost_model_id._generate_cost_lines()
        
        self.state = 'costed'
        
        return {
            'type': 'ir.actions.act_window',
            'name': '成本分析',
            'res_model': 'cpq.cost.model',
            'res_id': self.cost_model_id.id,
            'view_mode': 'form',
            'target': 'current'
        }
    
    def action_set_price(self):
        """设置价格并进入定价状态"""
        self.ensure_one()
        
        if not self.cost_model_id:
            raise UserError('请先进行成本核算！')
        
        if not self.unit_price or self.unit_price == 0:
            # 如果没有设置价格，使用默认加成率
            default_markup = 1.15  # 默认15%加成
            self.unit_price = self.unit_cost * default_markup
        
        self.state = 'priced'
    
    def action_submit_approval(self):
        """提交审批"""
        self.ensure_one()
        
        if self.state != 'priced':
            raise UserError('只有已定价的报价才能提交审批！')
        
        # 创建审批流
        self._create_approval_flow()
        
        self.state = 'submitted'
    
    def action_approve(self):
        """批准报价"""
        self.ensure_one()
        
        if self.state != 'submitted':
            raise UserError('只有已提交审批的报价才能批准！')
        
        if self.approval_status != 'approved':
            raise UserError('还有待审批的项目！')
        
        self.state = 'approved'
    
    def action_send_to_customer(self):
        """发送给客户"""
        self.ensure_one()
        
        if self.state != 'approved':
            raise UserError('只有已批准的报价才能发送给客户！')
        
        self.state = 'sent'
        
        # TODO: 发送邮件
        # self.message_post_with_template(...)
    
    def action_mark_won(self):
        """标记为赢单"""
        self.ensure_one()
        self.state = 'won'
    
    def action_mark_lost(self):
        """标记为丢单"""
        self.ensure_one()
        self.state = 'lost'
    
    def action_cancel(self):
        """取消报价"""
        self.ensure_one()
        if self.state in ['won', 'lost']:
            raise UserError('已赢单或丢单的报价不能取消！')
        self.state = 'cancelled'
    
    def action_reset_to_draft(self):
        """重置为草稿"""
        self.ensure_one()
        if self.state == 'won':
            raise UserError('已赢单的报价不能重置！')
        self.state = 'draft'
    
    def action_view_approvals(self):
        """查看审批"""
        self.ensure_one()
        return {
            'type': 'ir.actions.act_window',
            'name': '审批流程',
            'res_model': 'cpq.approval',
            'view_mode': 'list,form',
            'domain': [('quotation_id', '=', self.id)],
            'context': {'default_quotation_id': self.id}
        }
    
    def _create_approval_flow(self):
        """根据报价金额和利润率自动创建审批流"""
        self.ensure_one()
        
        # 清除旧的审批记录
        self.approval_ids.unlink()
        
        approval_rules = []
        
        # 规则1: 成本主管必审
        approval_rules.append(('cost_controller', 10))
        
        # 规则2: 总金额>100万需销售经理审批
        if self.total_amount > 1000000:
            approval_rules.append(('sales_manager', 20))
        
        # 规则3: 利润率<10%需财务经理审批
        if self.margin_rate < 10:
            approval_rules.append(('finance_manager', 30))
        
        # 规则4: 总金额>500万需总经理审批
        if self.total_amount > 5000000:
            approval_rules.append(('general_manager', 40))
        
        # 创建审批记录
        for role, sequence in approval_rules:
            approver = self._get_approver_by_role(role)
            if approver:
                self.env['cpq.approval'].create({
                    'quotation_id': self.id,
                    'sequence': sequence,
                    'approver_id': approver.id,
                    'role': role,
                    'state': 'pending'
                })
    
    def _get_approver_by_role(self, role):
        """根据角色获取审批人"""
        # TODO: 实现角色到用户的映射
        # 这里可以从公司设置或用户组中获取
        # 暂时返回当前用户的上级或管理员
        if role == 'cost_controller':
            group = self.env.ref('cpq_qms.group_cpq_cost_controller', raise_if_not_found=False)
        elif role == 'sales_manager':
            group = self.env.ref('cpq_qms.group_cpq_manager', raise_if_not_found=False)
        elif role == 'finance_manager':
            group = self.env.ref('account.group_account_manager', raise_if_not_found=False)
        elif role == 'general_manager':
            group = self.env.ref('base.group_system', raise_if_not_found=False)
        else:
            return False
        
        if group and group.users:
            return group.users[0]
        return False
    
    def _check_approval_completion(self):
        """检查审批是否全部完成"""
        self.ensure_one()
        if all(approval.state == 'approved' for approval in self.approval_ids):
            self.action_approve()

